#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2024/4/22 10:44
# @File    : thead_contrl.py
# @Description : -i http://pypi.tuna.tsinghua.edu.cn/simple/ --trusted-host pypi.tuna.tsinghua.edu.cn

import sys
import threading
import time
from concurrent.futures import ThreadPoolExecutor

import logging



class MyThread(threading.Thread):
    """ - """
    #dict_ = [{"kill": False} for i in range(1000)]
    def __init__(self, group=None, target=None, name=None,
                 args=(), kwargs=None, daemon=True, dict_: dict = {}):
        threading.Thread.__init__(self, group=group, target=target, name=name,
                                  args=args, kwargs=kwargs, daemon=daemon)

        self.killed = dict_ if dict_ else {"kill": False}

    def start(self):
        print(f"开启线程{self}")
        self.__run_backup = self.run
        self.run = self.__run
        threading.Thread.start(self)

    def __run(self):
        sys.settrace(self.globaltrace)
        self.__run_backup()
        self.run = self.__run_backup

    def globaltrace(self, frame, event, arg):
        if event == 'call':
            return self.localtrace
        else:
            return None

    def localtrace(self, frame, event, arg):
        if self.killed["kill"]:
            if event == 'line':
                if self.killed["kill"] == 1:
                    raise SystemExit()
                elif self.killed["kill"] == 2:
                    while self.killed["kill"]:
                        time.sleep(0.1)
        return self.localtrace

    def stop(self):
        print(f"停止线程{self}")
        self.killed["kill"] = 1

    def pause(self):
        print(f"暂停线程{self}")
        self.killed["kill"] = 2

    def resume(self):
        print(f"恢复线程{self}")
        self.killed["kill"] = False


class Task():

    def __init__(self, batch, epoch, target):
        """

        :param batch:
        :param epoch:
        :param target:
        """
        self.batch = batch
        self.epoch = epoch
        self.job = target
        #producer
        #consumer
        self.result = []
        self.result_dict = {}
        self.switch = self.__init_task__()

    def __init_task__(self):
        return MyThread(target=self.task, name="master")

    def task(self):
        batch = self.batch
        target = self.epoch
        mutex = threading.Lock()
        with ThreadPoolExecutor(max_workers=batch, thread_name_prefix='T') as pool:
            task = [pool.submit(self.job, event=_) for _ in range(batch)]
            finish = batch
            all_done = False
            # t = pool.submit(self.job, event=1)

            while not all_done:
                # 整个batch 全为true表示 任务完成
                for _, t in enumerate(task):
                    if t.done():
                        try:
                            mutex.acquire()
                            # 针对已完成的job 进行更新任务
                            if finish < target:
                                task[_] = pool.submit(self.job, finish)
                                all_done = False
                            else:
                                del task[_]
                                all_done = True
                            self.result.append(t.result())
                            self.result_dict[_] = t.result()
                        finally:
                            mutex.release()
                        finish += 1
                    else:
                        all_done = False

    def task2(self):
        ts = [MyThread(target=self.job) for n in list("ABCDE")]
        #[t.start() for t in ts]


def my_test_func(num):
    for i in range(num):
        time.sleep(1)
        print(i)


def demo():
    """ 线程 """
    t = MyThread(target=my_test_func, args=(100,))
    t.start()
    time.sleep(3)
    t.pause()
    time.sleep(3)
    t.resume()
    time.sleep(3)
    t.stop()
    # input()


import numpy as np
def my_target(event):
    sum = 0
    n = np.random.randint(3, 6)
    for i in range(n):
        time.sleep(.1)
        sum += i
        print(f"threadName:{threading.current_thread().getName()}, ThreadID:{threading.current_thread().native_id}, item:{i}")
    return (n, sum)


if __name__ == '__main__':

    #Ademo()
    t = Task(6, 6, my_target)
    switch = t.switch
    switch.start()
    switch.join()
    print(t.result)
    print(t.result_dict)

